package com.swapbytes.jrexportcmd;

import com.swapbytes.jrexportcmd.Types.*;
import java.io.ByteArrayOutputStream;
import java.sql.Connection;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JasperRunManager;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.export.ooxml.JRDocxExporter;
import net.sf.jasperreports.engine.util.JRLoader;
import org.apache.commons.codec.binary.Base64;

/**
 * Clase encargada en generar cada uno de los reportes al formato solicitado.
 *
 * @author Nicola Strappazzon C., nicola51980@gmail.com
 * @version 1.2.0
 */
public class Export {

    private JasperReport _report = null;
    private Connection _cn = null;
    private Map _parameters = null;
    private String _PathIn = null;
    private String _PathOut = null;
    private Types.Format _format = null;
    private Types.Stream _stream = null;

    /**
     * Define la conexion al manejador de base de datos usado por el reporte para
     * poder generarse.
     *
     * @param cn
     */
    public void setConnection(Connection cn) {
        this._cn = cn;
    }

    /**
     * Carga y/o compila desde la ruta de entrada el reporte que sera procesado.
     */
    public void loadReport() {
        if(this.getExtension().equals("jrxml")) {
            try {
                this._report = JasperCompileManager.compileReport(this._PathIn);
            } catch (JRException ex) {
                Logger.getLogger(Export.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else if(this.getExtension().equals("jasper")) {
            try {
                this._report = (JasperReport) JRLoader.loadObjectFromLocation(this._PathIn);
            } catch (JRException ex) {
                Logger.getLogger(Export.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    /**
     * Extrae la extensión del archivo.
     *
     * @return
     */
    private String getExtension() {
        return this._PathIn.substring(this._PathIn.lastIndexOf('.') + 1).toLowerCase();
    }

    /**
     * Define los parametros que son necesarios para procesar un reporte.
     *
     * @param parameters
     */
    public void setParameters(Map parameters) {
        this._parameters = parameters;
    }

    /**
     * Define la ruta del sistema de archivos de un reporte JRXML para ser procesado.
     *
     * @param pathIn
     */
    public void setInput(String pathIn) {
        this._PathIn = pathIn;
    }

    /**
     * Define la ruta del sistema de archivos como destino de un reporte ya procesado.
     *
     * @param pathOut
     */
    public void setOutput(String pathOut) {
        this._PathOut = pathOut;
    }

    /**
     * Define el formato del stream para la salida de un reporte a procesar.
     *
     * @param stream
     */
    public void setStream(Types.Stream stream) {
        this._stream = stream;
    }

    /**
     * Define el formato de salida de un reporte a procesar.
     *
     * @param format
     */
    public void setFormat(Types.Format format) {
        this._format = format;
    }

    /**
     * Genera el reporte para ser exportado.
     */
    public void generateReport() {
        switch (this._format) {
            case PDF:
                if (this._PathOut != null) {
                    this.getPDFFile();
                } else {
                    this.getPDFStream();
                }
                break;
            case XLS:
                if (this._PathOut != null) {
                    this.getXLSFile();
                } else {
                    this.getXLSStream();
                }
                break;
            case DOCX:
                if (this._PathOut != null) {
                    this.getDOCXFile();
                } else {
                    this.getDOCXStream();
                }
                break;
        }
    }

    /**
     * Genera el reporte en formato PDF y lo exporta a un archivo.
     */
    private void getPDFFile() {
        try {
            JRPdfExporter pdfExporter = new JRPdfExporter();
            JasperPrint print = JasperFillManager.fillReport(this._report, this._parameters, this._cn);

            pdfExporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
            pdfExporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, this._PathOut);
            pdfExporter.exportReport();
        } catch (JRException ex) {
            Logger.getLogger(Export.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Genera el reporte en formato XLS y lo exporta a un archivo.
     */
    private void getXLSFile() {
        try {
            JRXlsExporter exporter = new JRXlsExporter();
            JasperPrint print = JasperFillManager.fillReport(this._report, this._parameters, this._cn);

            exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
            exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, this._PathOut);
//	  exporter.setParameter(JRXlsExporterParameter.IS_AUTO_DETECT_CELL_TYPE, Boolean.TRUE);
//	  exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
//	  exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
//	  exporter.setParameter(JExcelApiExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
            exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.TRUE);
            exporter.exportReport();
        } catch (JRException ex) {
            Logger.getLogger(Export.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Genera el reporte en formato DOCX y lo exporta a un archivo.
     */
    private void getDOCXFile() {
        try {
            JRDocxExporter exporter = new JRDocxExporter();
            JasperPrint print = JasperFillManager.fillReport(this._report, this._parameters, this._cn);

            exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
            exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, this._PathOut);
            exporter.exportReport();
        } catch (JRException ex) {
            Logger.getLogger(Export.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Genera el reporte en formato PDF y lo exporta a un stream.
     */
    private void getPDFStream() {
        byte[] stream = null;
        
        try {
            stream = JasperRunManager.runReportToPdf(this._report, this._parameters, this._cn);
        } catch (JRException ex) {
            Logger.getLogger(Export.class.getName()).log(Level.SEVERE, null, ex);
        }

        switch(this._stream) {
            case BASE64:
                byte[] encoded = Base64.encodeBase64(stream);
                String encodedString = new String(encoded);
                System.out.print(encodedString);
                break;
            case BIN:
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                outputStream.write(stream, 0, stream.length);
                System.out.print(outputStream.toString());
                break;
        }
    }

    /**
     * Genera el reporte en formato XLS y lo exporta a un stream.
     */
    private void getXLSStream() {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        JRXlsExporter         exporter     = new JRXlsExporter();
        JasperPrint           print        = null;

        try {
            print = JasperFillManager.fillReport(this._report, this._parameters, this._cn);
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
            exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.TRUE);
            exporter.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, outputStream);
            exporter.exportReport();
        } catch (JRException ex) {
            Logger.getLogger(Export.class.getName()).log(Level.SEVERE, null, ex);
        }
 
        switch(this._stream) {
            case BASE64:
                byte[] encoded = Base64.encodeBase64(outputStream.toByteArray());
                String encodedString = new String(encoded);
                System.out.print(encodedString);
                break;
            case BIN:
                System.out.print(outputStream.toString());
                break;
        }
    }

    /**
     * Genera el reporte en formato DOCX y lo exporta a un stream.
     */
    private void getDOCXStream() {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        JRDocxExporter        exporter = new JRDocxExporter();
        JasperPrint           print        = null;

        try {
            print = JasperFillManager.fillReport(this._report, this._parameters, this._cn);
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
            exporter.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, outputStream);
            exporter.exportReport();
        } catch (JRException ex) {
            Logger.getLogger(Export.class.getName()).log(Level.SEVERE, null, ex);
        }

        switch(this._stream) {
            case BASE64:
                byte[] encoded = Base64.encodeBase64(outputStream.toByteArray());
                String encodedString = new String(encoded);
                System.out.print(encodedString);
                break;
            case BIN:
                System.out.print(outputStream.toString());
                break;
        }
    }
}
